﻿using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Management.Instrumentation;
using System.Net;
using System.Net.Sockets;
using System.ServiceModel.Channels;
using System.Text;
using System.Threading;
using Kugar.Core.Collections;
using Kugar.Core.ExtMethod;
using Kugar.Core.BaseStruct;


namespace Kugar.Core.Communications.Transfer
{
    public class NewRUDP
    {
        private const int RUPLinkCount = 5;

        private Socket _socket = null;
        private int _port;
        private BufferManager _bufferManager = BufferManager.CreateBufferManager(10 * 1024 * 1024, 10 * 1024);
        //private RUDPLink[] _cacheConnectList = null;
        private IAutoTimeoutSet<int, int?> _cacheHandShakeTempID = new IntKeyAutoTimeoutSet<int?>(10000);
        //private IAutoTimeoutSet<int, ConnectConfig> _cacheEnabledConnectID = new IntKeyAutoTimeoutSet<ConnectConfig>(10000);
        private IntIndexDictioanry<ConnectConfig> _cacheEnabledConnectID = new IntIndexDictioanry<ConnectConfig>(1, 1000);
        private ConcurrentDictionary<int, ConnectAsyncResult> _cacheAsyncResult = new ConcurrentDictionary<int, ConnectAsyncResult>();
        private CallbackTimer _callbackTimer = new CallbackTimer(2, 2);

        private short _defaultWindowSize = 5;
        private int _localBufferLength = 0;
        private int _pageSize = 0;
        private bool _enableAcceptConnect = false;

        internal DateTime Now = DateTime.Now;

        public NewRUDP(int port)
            : this(port, 5, 548)
        {
        }

        public NewRUDP(int port, short windowSize, int dataPageSize)
        {
            //_cacheConnectList = new RUDPLink[RUPLinkCount];

            //for (int i = 0; i < _cacheConnectList.Length; i++)
            //{
            //    _cacheConnectList[i] = new RUDPLink(this, _bufferManager);
            //}

            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

            _socket.Bind(new IPEndPoint(IPAddress.Any, port));

            _defaultWindowSize = windowSize;

            _pageSize = Math.Min(dataPageSize - 25, _socket.ReceiveBufferSize);

            _localBufferLength = (_pageSize * 2).ToMinInt(100);

            EndPoint remotePoint = new IPEndPoint(IPAddress.Any, 0);

            var buff = _bufferManager.TakeBuffer(_localBufferLength);

            _socket.BeginReceiveFrom(buff, 0, _localBufferLength, SocketFlags.None, ref remotePoint, SocketDataReceive, buff);

        }

#if DEBUG

        public string Rule { set; get; }

#endif

        public void Listen()
        {
            _enableAcceptConnect = true;
            //EndPoint remotePoint=new IPEndPoint(IPAddress.Any,0);

            //var buff=_bufferManager.TakeBuffer(8192);

            //_socket.BeginReceiveFrom(buff, 0, 8192, SocketFlags.None, ref remotePoint, SocketDataReceive, buff);
        }

        public void StopListen()
        {
            _enableAcceptConnect = false;
        }

        public int Port { get { return _port; } }

        public RUDPConnection ConnectTo(IPEndPoint remotePoint)
        {
            return null;

        }

        public IAsyncResult BeginConnectTo(IPEndPoint remotePoint, AsyncCallback callback, object state)
        {
            var bagID = _cacheHandShakeTempID.TaskItem(null);
            var buff = buildConnectRequest(bagID);

            _cacheAsyncResult.Add(bagID, new ConnectAsyncResult(bagID, callback, state));

            SendData(buff.Array, buff.Offset, buff.Count, remotePoint, null, null);

            return null;
        }

        public RUDPConnection EndConnectTo(IAsyncResult iar)
        {
            if (!(iar is ConnectAsyncResult))
            {
                return null;
            }

            var asyncResult = (ConnectAsyncResult)iar;

            var connectID = asyncResult.ConnectID;

            if (_cacheAsyncResult.ContainsKey(asyncResult.BagID))
            {
                _cacheAsyncResult.Remove(asyncResult.BagID);

            }

            ConnectConfig config = _cacheEnabledConnectID[connectID];

            if (config != null)
            {
                return config.Item;
            }
            else
            {
                throw new InstanceNotFoundException("未存在指定的链接");
            }


            //foreach (var rudpLink in _cacheConnectList)
            //{
            //    if (rudpLink.ContansConnection(connectID))
            //    {
            //        return rudpLink[connectID];
            //    }
            //}

            //throw new InstanceNotFoundException("未存在指定的链接");
        }

        public event EventHandler<RUDPConnectRequestEventArgs> ConnectRequest;

        public event EventHandler<RUDPConnectSuccessEventArgs> ConnectSuccess;

        public event EventHandler<RUDPDisconnectedEventArgs> Disconnected;



        internal void SendData(byte[] data, int offset, int count, IPEndPoint remotePoint, WaitCallback callback, object state)
        {
            SocketFlags flags;

            if (remotePoint.Address == IPAddress.Broadcast)
            {
                flags = SocketFlags.Broadcast;


            }
            else
            {
                flags = SocketFlags.None;
            }

            _socket.BeginSendTo(data, offset, count, flags, remotePoint,
                                                                            (iar) =>
                                                                            {
                                                                                try
                                                                                {
                                                                                    _socket.EndSendTo(iar);
                                                                                }
                                                                                catch (Exception)
                                                                                {
                                                                                }

                                                                                if (callback != null)
                                                                                {
                                                                                    callback(state);
                                                                                }

                                                                            }, null);

        }

        internal bool OnConnectRequest(IPEndPoint remotePoint)
        {
            if (ConnectRequest != null)
            {
                var e = new RUDPConnectRequestEventArgs(remotePoint);
                ConnectRequest(this, e);

                return e.Cancel;
            }
            else
            {
                return false;
            }
        }

        internal void OnConnectSuccess(RUDPConnection item)
        {
            if (ConnectSuccess != null)
            {
                Events.EventHelper.RaiseAsync(ConnectSuccess, this, new RUDPConnectSuccessEventArgs(item));
            }
        }

        internal void OnDisconnected(RUDPDisconnectedEventArgs e)
        {
            _cacheEnabledConnectID.ReturnValue(e.Connection.ConnectID);
            Events.EventHelper.RaiseAsync(Disconnected, this, e);

        }


        //负责处理Socket的数据接收操作
        private void SocketDataReceive(IAsyncResult iar)
        {
            EndPoint oldEndPoint = new IPEndPoint(IPAddress.Any, 0); ;
            int readCount = 0;

            try
            {
                readCount = _socket.EndReceiveFrom(iar, ref oldEndPoint);
            }
            catch (Exception)
            {
                return;
            }

            var newBuff = _bufferManager.TakeBuffer(_localBufferLength);

            EndPoint tempRemotePoint = new IPEndPoint(IPAddress.Any, 0);

            _socket.BeginReceiveFrom(newBuff, 0, _localBufferLength, SocketFlags.None, ref tempRemotePoint, SocketDataReceive, newBuff);



            var buff = (byte[])iar.AsyncState;

            if (readCount > 4)
            {
                var cmdByte = buff[1];

                if (buff.GetCRCCode(0, readCount) != 0 || //CRC校验错误
                   !CheckCmd(buff, 0, readCount))  //指令码不在范围之内
                {
                    _bufferManager.ReturnBuffer(buff);
                    return;
                }


                var cmd = (RUDPCmd)cmdByte;

                switch (cmd)
                {
                    case RUDPCmd.HandShake_ConnectRequest:
                    case RUDPCmd.HandShake_ConnectResponse:
                    case RUDPCmd.HandShake_ConnectSuccess:
                        HandShakeReceive(cmd, buff, 0, readCount, (IPEndPoint)oldEndPoint);
                        break;
                    case RUDPCmd.HandShake_Fin:
                    case RUDPCmd.HandShake_FinSendClear:
                    case RUDPCmd.HandShake_FinSendClear_ACK:
                    case RUDPCmd.HandShake_Fin_ACK:
                    case RUDPCmd.Data:
                    case RUDPCmd.DataACK:
                        DataItemReceive(cmd, buff, 0, readCount);
                        break;


                    case RUDPCmd.KeepActive:

                        break;

                }
            }


        }

        //除数据连接以及连接保活指令由RUDPServer类处理之外，其他指令均转发到相应的ConnectConfig中处理
        private void DataItemReceive(RUDPCmd cmd, byte[] data, int offset, int count)
        {
            var connectID = BitConverter.ToInt32(data, offset + 2);

            if (!_cacheEnabledConnectID.ContainsID(connectID))
            {
                return;
            }

            //_cacheEnabledConnectID.ActiveItem(connectID);

            var c = _cacheEnabledConnectID[connectID];

            if (c != null)
            {
                c.DataReceive(cmd, data, offset, count);
            }

            //RUDPLink link = _cacheConnectList.FindItem((r) => r.ContansConnection(connectID));

            //if (link != null)
            //{
            //    link.DataReceive(connectID, data, offset, count);
            //}

        }

        #region "连接握手处理"

        private void HandShakeReceive(RUDPCmd cmd, byte[] data, int offset, int count, IPEndPoint remotePoint)
        {


            switch (cmd)
            {
                case RUDPCmd.HandShake_ConnectRequest:   //客户端发送，服务器端处理
                    {
                        if (_enableAcceptConnect && !OnConnectRequest(remotePoint))
                        {
                            var connectID = _cacheEnabledConnectID.TaskItem(null);
                            var srcBagID = BitConverter.ToInt32(data, offset + 2);
                            _cacheHandShakeTempID.AddValue(srcBagID, connectID);
                            var buff = buildConnectResponse(connectID, srcBagID);
                            SendData(buff.Array, buff.Offset, buff.Count, remotePoint, s => _bufferManager.ReturnBuffer(buff.Array), null);
                        }

                    }


                    break;

                case RUDPCmd.HandShake_ConnectResponse:  //服务器端发送，客户端处理
                    {
                        //当客户端接收到该指令时，表示服务器端连接接受
                        var srcBagID = BitConverter.ToInt32(data, offset + 2);
                        var connectID = BitConverter.ToInt32(data, offset + 6);

                        if (!_cacheEnabledConnectID.ContainsID(connectID) &&    //是否为已经成功的连接
                            (_cacheHandShakeTempID.ContainsID(srcBagID) ||        //是否为正在连接的ID
                             _cacheAsyncResult.ContainsKey(srcBagID))                    //是否为异步连接的ID
                            )
                        {
                            var buff = buildConnectSuccess(data, offset, count);

                            var pageDataSize = BitConverter.ToInt32(data, offset + 10);
                            var windowSize = Math.Min(data[offset + 14], _defaultWindowSize);

                            addNewConnection(connectID, remotePoint, pageDataSize, windowSize);

                            _cacheHandShakeTempID.ReturnValue(srcBagID);

                            SendData(buff.Array, buff.Offset, buff.Count, remotePoint, (s) => _bufferManager.ReturnBuffer(buff.Array), null);

                            //异步回调
                            var asyncResult = _cacheAsyncResult[srcBagID];

                            if (asyncResult != null)
                            {
                                asyncResult.IsCompleted = true;
                                asyncResult.ConnectID = connectID;
                                asyncResult.Execute();
                            }

                        }
                    }
                    break;
                case RUDPCmd.HandShake_ConnectSuccess:  //客户端发送，服务器端处理
                    //服务器端接收到该指令后，表示服务器端连接完成
                    {
                        var connectID = BitConverter.ToInt32(data, offset + 6);
                        var srcBagID = BitConverter.ToInt32(data, offset + 2);

                        if (_cacheEnabledConnectID.ContainsID(connectID) &&
                             (_cacheHandShakeTempID.ContainsID(srcBagID) &&
                             _cacheHandShakeTempID[srcBagID] == connectID))
                        {
                            lock (_cacheEnabledConnectID)
                            {
                                if (_cacheEnabledConnectID[connectID] == null)
                                {
                                    var revPageSize = BitConverter.ToInt32(data, offset + 10);
                                    var windowSize = (short)data[offset + 14];

                                    var rudp = addNewConnection(connectID, remotePoint, revPageSize, windowSize);

                                    if (rudp != null)
                                    {
                                        _cacheHandShakeTempID.ReturnValue(srcBagID);

                                        OnConnectSuccess(rudp);
                                    }
                                }
                            }
                        }

                        break;
                    }

                default:
                    break;
            }

            _bufferManager.ReturnBuffer(data);
        }

        private ArraySegment<byte> buildConnectResponse(int connectID, int srcID)
        {
            var buff = _bufferManager.TakeBuffer(17);

            var bs = new ByteStream(buff);

            bs.WriteByte(0x01);
            bs.WriteByte((byte)RUDPCmd.HandShake_ConnectResponse);
            bs.Write(BitConverter.GetBytes(srcID));
            bs.Write(BitConverter.GetBytes(connectID));
            bs.Write(BitConverter.GetBytes(_pageSize));
            bs.WriteByte((byte)_defaultWindowSize);
            bs.Write(buff.GetCRCCodeBytes(0, 15));

            bs.Close();
            bs.Dispose();

            return new ArraySegment<byte>(buff, 0, 17);
        }

        private ArraySegment<byte> buildConnectRequest(int bagID)
        {
            var buff = _bufferManager.TakeBuffer(9);

            var bs = new ByteStream(buff);

            bs.WriteByte(0x01);
            bs.WriteByte((byte)RUDPCmd.HandShake_ConnectRequest);
            bs.Write(BitConverter.GetBytes(bagID));
            bs.WriteByte((byte)_defaultWindowSize);
            bs.Write(buff.GetCRCCodeBytes(0, 7));

            bs.Close();
            bs.Dispose();

            return new ArraySegment<byte>(buff, 0, 9);
        }

        /// <summary>
        ///     
        /// </summary>
        /// <param name="revData">接收到的HandShake_ConnectResponse指令</param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        private ArraySegment<byte> buildConnectSuccess(byte[] revData, int offset, int count)
        {
            var bagID = BitConverter.ToInt32(revData, offset + 2);
            var connectID = BitConverter.ToInt32(revData, offset + 6);
            var serverPageSize = BitConverter.ToInt32(revData, offset + 10);
            var serverWindowSize = (short)revData[offset + 14];

            var revPageSize = Math.Min(serverPageSize, _pageSize);
            var windowSize = (short)Math.Min(serverWindowSize, _defaultWindowSize);

            var buff = _bufferManager.TakeBuffer(17);

            var bs = new ByteStream(buff);

            bs.WriteByte(0x01);
            bs.WriteByte((byte)RUDPCmd.HandShake_ConnectSuccess);
            bs.Write(BitConverter.GetBytes(bagID));
            bs.Write(BitConverter.GetBytes(connectID));
            bs.Write(revPageSize);
            bs.WriteByte((byte)windowSize);
            bs.Write(buff.GetCRCCodeBytes(0, 15));

            bs.Close();
            bs.Dispose();

            return new ArraySegment<byte>(buff, 0, 17);
        }

        private RUDPConnection addNewConnection(int connectID, IPEndPoint remotePoint, int pageSize, short windowSize)
        {
            ConnectConfig connectConfig = null;

            lock (_cacheEnabledConnectID)
            {
                connectConfig = new ConnectConfig(this, connectID, windowSize, pageSize, remotePoint, _bufferManager, _callbackTimer);

                //_cacheConnect.Add(connectID, connectConfig);
                //foreach (var rudpLink in _cacheConnectList)
                //{
                //    if (rudpLink != minLink && rudpLink.Count < minLink.Count)
                //    {
                //        minLink = rudpLink;
                //    }
                //}

                //rudpItem = minLink.AddConnection(connectID, pageSize - 13 - 50, windowSize, remotePoint);

                _cacheEnabledConnectID.AddOrUpdate(connectID, connectConfig);
            }

            return connectConfig.Item;
        }

        #endregion

        private bool CheckCmd(byte[] data, int offset, int count)
        {
            bool retValue = false;
            switch (data[offset])
            {
                case 1:
                    {
                        var cmdByte = data[offset + 1];
                        if ((cmdByte >= 0x00 && cmdByte <= 0x03) ||
                           (cmdByte >= 0xF0 && cmdByte <= 0xF6) ||
                           (cmdByte >= 0xE0 && cmdByte <= 0xE1))  //指令码不在范围之内                        
                        {
                            retValue = true;
                        }
                    }
                    break;

            }

            return retValue;
        }

        private class ConnectAsyncResult : IAsyncResult
        {
            private AsyncCallback _callback = null;
            private object _state = null;
            private int _connectID = 0;
            private int _bagID = 0;

            public ConnectAsyncResult(int bagID, AsyncCallback callback, object state)
            {
                _callback = callback;
                _state = state;
                _bagID = bagID;
            }

            internal void Execute()
            {
                ThreadPool.QueueUserWorkItem((o) =>
                                                 {
                                                     if (_callback != null)
                                                     {
                                                         _callback((IAsyncResult)o);
                                                     }
                                                 }, this);

            }

            internal int ConnectID
            {
                get { return _connectID; }
                set { _connectID = value; }
            }

            internal int BagID { get { return _bagID; } }

            #region Implementation of IAsyncResult

            public bool IsCompleted
            {
                get { throw new NotImplementedException(); }
                internal set { }
            }


            public WaitHandle AsyncWaitHandle
            {
                get { throw new NotImplementedException(); }
            }

            public object AsyncState
            {
                get { return _state; }
            }

            public bool CompletedSynchronously
            {
                get { throw new NotImplementedException(); }
            }

            #endregion
        }
    }

    internal class ConnectConfig : MarshalByRefObject
    {
        private SlideWindowRevQueue _revQueue;
        private SlideWindowSendQueue _sendQueue;
        volatile short _windowSize;
        int _dataPageSize;
        int _connectID;
        IPEndPoint _remotePoint;
        private NewRUDP _udpServer = null;
        private bool _closed = false;
        private ConnectStatus _status = ConnectStatus.None;
        private BufferManager _bufferManager = null;
        private CallbackTimer _callbackTimer = null;
        private byte _protocolVer = 1;
        private byte[] _connectIDBytes = null;
        private byte[] _keepActiveBytes = new byte[8];
        private DateTime _lastDataTransfer;


        public ConnectConfig(NewRUDP udpServer, int connectID, short windowSize, int dataPageSize, IPEndPoint remotePoint, BufferManager bufferManager, CallbackTimer callbackTimer)
        {
            _windowSize = windowSize;
            _dataPageSize = dataPageSize;
            _remotePoint = remotePoint;
            _connectID = connectID;
            _bufferManager = bufferManager;
            _callbackTimer = callbackTimer;

            _lastDataTransfer = DateTime.Now;

            _connectIDBytes = BitConverter.GetBytes(connectID);

            Item = new RUDPConnection(connectID, this);
            _udpServer = udpServer;

            _sendQueue = new SlideWindowSendQueue(this, 0, bufferManager);
            _revQueue = new SlideWindowRevQueue(this, 0, bufferManager);

            _revQueue.DataReceived += OnDataReceived;

            _sendQueue.SendClear += _sendQueue_SendClear;


            var bs = new ByteStream(_keepActiveBytes);

            bs.Write(_protocolVer);
            bs.Write((byte)RUDPCmd.KeepActive);
            bs.Write(_connectIDBytes);
            bs.Write(_keepActiveBytes.GetCRCCode(0, 6));

            bs.Close();
            bs.Dispose();
        }

        public short WindowSize
        {
            get { return _windowSize; }
            set
            {
                //Interlocked.Exchange(ref _windowSize, value);
                _windowSize = value;
            }
        }
        public int DataPageSize
        {
            get
            {
                return _dataPageSize;
            }
            set
            {
                Interlocked.Exchange(ref _dataPageSize, value);
            }

        }
        public int ConnectID { get { return _connectID; } }
        public RUDPConnection Item;
        public IPEndPoint RemotePoint { get { return _remotePoint; } }

        public IAsyncResult BeginSend(byte[] data, int offset, int count, AsyncCallback callback, object state)
        {
            if (_closed)
            {
                return null;
            }

            return _sendQueue.BeginSend(data, offset, count, callback, state);
        }

        public int EndSend(IAsyncResult iar)
        {
            return _sendQueue.EndSend(iar);
        }

        internal void Disconnection()
        {
            this.Close();

            var e = new RUDPDisconnectedEventArgs(Item, new RUDPRemoteNoResponseException());

            Item.OnDisconnected(e);

            _udpServer.OnDisconnected(e);

        }

        internal void SendData(byte[] data, int offset, int count, WaitCallback callback, object state)
        {
            _udpServer.SendData(data, offset, count, _remotePoint, callback, state);
        }

        internal TimerPool TimePool { get; private set; }

        internal void DataReceive(RUDPCmd cmd, byte[] data, int offset, int count)
        {
            if (_closed)
            {
                return;
            }

            switch (cmd)
            {
                case RUDPCmd.Data:
                    _revQueue.EnQueue(RevItemSegment.Load(data, offset, count));// EnQueueDataItem(data, offset, count);
                    break;
                case RUDPCmd.DataACK:
                    _sendQueue.EnQueueACK(data, offset, count);
                    break;
                case RUDPCmd.HandShake_Fin:
                case RUDPCmd.HandShake_Fin_ACK:
                case RUDPCmd.HandShake_FinSendClear:
                case RUDPCmd.HandShake_FinSendClear_ACK:
                    HandleCloseConnect(cmd, data, offset, count);
                    break;
                case RUDPCmd.KeepActive_ACK:
                    OnReviceKeepActiveACK();
                    break;
            }
        }

        internal void Start()
        {
            _status = ConnectStatus.ESTABLISHED;
        }

        internal void Stop()
        {
            _status = ConnectStatus.Stop;
        }

        #region "数据接收相关"

        private void OnDataReceived(object sender, RUDPDataReceivedEventArgs e)
        {
            Item.OnReceiveData(e);
        }

        #endregion

        #region "关闭连接相关"

        private void Close()
        {
            //StartClose();
            _closed = true;
            _sendQueue.Close();
            _revQueue.Close();

            var e = new RUDPDisconnectedEventArgs(Item);

            Item.OnDisconnected(e);

            _udpServer.OnDisconnected(e);

            _udpServer = null;
        }

        internal void StartClose()
        {
            var dt = buildFinRequest();

            SendData(dt.Array, dt.Offset, dt.Count, ReturnBuffer, dt.Array);

            this._status = ConnectStatus.Fin_Wait1;

            //_callbackTimer.Call(20000, (o) =>
            //{
            //    if (this._status == ConnectStatus.Fin_Wait1)
            //    {
            //        StartClose();
            //    }
            //});
        }

        private void HandleCloseConnect(RUDPCmd cmd, byte[] data, int offset, int count)
        {
            switch (cmd)
            {
                case RUDPCmd.HandShake_Fin:  //被动关闭方接收到关闭指令后
                    this._status = ConnectStatus.Close_Wait;

                    var respData = buildFinRequestACK();

                    this.SendData(respData.Array, respData.Offset, respData.Count, ReturnBuffer, respData.Array);

                    _sendQueue.Stop();
                    break;
                case RUDPCmd.HandShake_Fin_ACK:
                    {
                        if (this._status == ConnectStatus.Fin_Wait1)
                        {
                            this._status = ConnectStatus.Fin_Wait2;
                        }
                    }

                    break;
                case RUDPCmd.HandShake_FinSendClear:  //主动关闭方接收到被动关闭方该消息时，表示被动方所有数据已经发送完毕，可以关闭连接
                    //发送ACK包
                    if (_status == ConnectStatus.Fin_Wait2 || _status == ConnectStatus.Time_Wait || _status == ConnectStatus.Fin_Wait1)
                    {
                        //有可能HandShake_FinSendClear与HandShake_Fin_ACK同时发出并先后被主动关闭方接收到
                        if (_status == ConnectStatus.Fin_Wait2 || _status == ConnectStatus.Fin_Wait1)
                        {
                            _revQueue.Stop();
                            this._status = ConnectStatus.Time_Wait;

                            _callbackTimer.Call(120000, (t) =>
                                                        {
                                                            this.Close();
                                                        }, null);
                        }

                        var dt = buildFinSendClearACK();

                        SendData(dt.Array, dt.Offset, dt.Count, ReturnBuffer, dt.Array);
                    }
                    break;
                case RUDPCmd.HandShake_FinSendClear_ACK:
                    {
                        if (_status == ConnectStatus.Last_ACK)
                        {
                            _status = ConnectStatus.Closed;
                            this.Close();
                            //Item.OnDisconnected();
                        }

                    }
                    break;
            }
        }

        private void Fin_SendClear()
        {
            var dt = buildFinSendClear();

            SendData(dt.Array, dt.Offset, dt.Count, ReturnBuffer, dt.Array);

            this._status = ConnectStatus.Last_ACK;

            _callbackTimer.Call(20000, (o) =>
                                       {
                                           if (this._status == ConnectStatus.Last_ACK)
                                           {
                                               Fin_SendClear();
                                           }
                                       });
        }

        private void _sendQueue_SendClear(object sender, EventArgs e)
        {
            if (_status == ConnectStatus.Close_Wait)
            {
                Fin_SendClear();
            }
        }

        private ArraySegment<byte> buildFinRequest()
        {
            byte[] buff = _bufferManager.TakeBuffer(8);

            var bs = new ByteStream(buff);

            bs.Write(_protocolVer);
            bs.Write((byte)RUDPCmd.HandShake_Fin);
            bs.Write(_connectIDBytes);
            bs.Write(buff.GetCRCCode(0, 6));

            bs.Close();
            bs.Dispose();

            return new ArraySegment<byte>(buff, 0, 8);
        }

        private ArraySegment<byte> buildFinRequestACK()
        {
            byte[] buff = _bufferManager.TakeBuffer(8);

            var bs = new ByteStream(buff);

            bs.Write(_protocolVer);
            bs.Write((byte)RUDPCmd.HandShake_Fin_ACK);
            bs.Write(_connectIDBytes);
            bs.Write(buff.GetCRCCode(0, 6));

            bs.Close();
            bs.Dispose();

            return new ArraySegment<byte>(buff, 0, 8);
        }

        private ArraySegment<byte> buildFinSendClear()
        {
            byte[] buff = _bufferManager.TakeBuffer(8);

            var bs = new ByteStream(buff);

            bs.Write(_protocolVer);
            bs.Write((byte)RUDPCmd.HandShake_FinSendClear);
            bs.Write(_connectIDBytes);
            bs.Write(buff.GetCRCCode(0, 6));

            bs.Close();
            bs.Dispose();

            return new ArraySegment<byte>(buff, 0, 8);
        }

        private ArraySegment<byte> buildFinSendClearACK()
        {
            byte[] buff = _bufferManager.TakeBuffer(8);

            var bs = new ByteStream(buff);

            bs.Write(_protocolVer);
            bs.Write((byte)RUDPCmd.HandShake_FinSendClear_ACK);
            bs.Write(_connectIDBytes);
            bs.Write(buff.GetCRCCode(0, 6));

            bs.Close();
            bs.Dispose();

            return new ArraySegment<byte>(buff, 0, 8);
        }

        private void ReturnBuffer(object state)
        {
            if (state is byte[])
            {
                _bufferManager.ReturnBuffer((byte[])state);
            }

        }

        #endregion

        #region "保活相关"


        private void CheckActive(object state)
        {
            if (_lastDataTransfer.AddSeconds(30) < _udpServer.Now)
            {
                SendData(_keepActiveBytes, 0, 8, null, null);
            }
        }

        private void OnReviceKeepActiveACK()
        {

            _lastDataTransfer = _udpServer.Now;
        }




        #endregion

        //public void AddAsyncResult(int bagID, SendAsyncResult iar)
        //{
        //    _cacheSendSyncResult.Add(bagID, iar);
        //}

        //public void RemoveAsyncResult(int bagID)
        //{
        //    Monitor.Enter(_cacheSendSyncResult);

        //    _cacheSendSyncResult.Remove(bagID);

        //    Monitor.Exit(_cacheSendSyncResult);
        //}

        //public SendAsyncResult GetAsyncResult(int bagID)
        //{
        //    SendAsyncResult iar = null;

        //    if (_cacheSendSyncResult.TryGetValue(bagID, out iar))
        //    {
        //        return iar;
        //    }
        //    else
        //    {
        //        return null;
        //    }
        //}

        //public int GetBagID()
        //{
        //    return Interlocked.Increment(ref _bagID); ;
        //}
    }

    //只负责管理发送队列和窗口
    internal class SlideWindowSendQueue
    {
        private ConcurrentQueue<SendDataSegment> _sendQueue = null;
        private readonly SortedList<int, SendDataSegment> _currentSendedWindow = null;
        private Dictionary<int, SendAsyncResult> _cacheSendSyncResult = new Dictionary<int, SendAsyncResult>(10);
        private AtomInt16 _nextSendIndex = null;
        private int _bagID = 0;
        private BufferManager _bufferManager = null;
        private ConnectConfig _config = null;
        private int _connectID;
        internal bool _isClosed = false;
        private TimerPool_Item _sendTimeoutCheckTimer = null;

        public SlideWindowSendQueue(ConnectConfig config, short startIndex, BufferManager bufferManager)
        {
            _sendQueue = new ConcurrentQueue<SendDataSegment>();
            _currentSendedWindow = new SortedList<int, SendDataSegment>(config.WindowSize);

            _config = config;

            _connectID = config.ConnectID;

            _nextSendIndex = new AtomInt16(startIndex);

            _bufferManager = bufferManager;

            //config.TimePool.Add(2000, SendTimeOutChecker, null, true);
        }

        internal IAsyncResult BeginSend(byte[] data, int offset, int count, AsyncCallback callback, object state)
        {
            if (_isClosed)
            {
                throw new Exception("连接已关闭,无法再发送新数据");
            }

            //int tempBagID = Interlocked.Increment(ref _bagID); ;

            int tempBagID = GetBagID();

            this.EnqueueData(tempBagID, data, offset, count);

            FillAndSend();

            var iar = new SendAsyncResult(tempBagID, count, callback, state);

            _cacheSendSyncResult.Add(tempBagID, iar);

            return iar;

        }

        internal int EndSend(IAsyncResult iar)
        {
            var item = (SendAsyncResult)iar;

            //if (item.Callback == null)
            //{
            //    throw new Exception();
            //}

            //ConnectConfig config = null;

            //if (_cacheConnectConfig.TryGetValue(item.ConnectID, out config))
            //{
            //    config.RemoveAsyncResult(item.BagID);
            //}

            //Monitor.Enter(_cacheSendSyncResult);

            //_cacheSendSyncResult.Remove(item.BagID);

            //Monitor.Exit(_cacheSendSyncResult);

            _cacheSendSyncResult.Remove(item.BagID);

            return item.DataLength;
        }

        internal void EnQueueACK(byte[] data, int offset, int count)
        {
            var ackCount = data[offset + 6];

            if (ackCount <= 0 || ackCount * 2 + 9 > count)
            {
                _bufferManager.ReturnBuffer(data);
                return;
            }

            for (int i = 0; i < ackCount; i += 2)
            {
                var ackIndex = BitConverter.ToInt16(data, offset + 7 + i);

                _currentSendedWindow.UpdateValue(ackIndex, (s) =>
                                                               {
                                                                   s.IsSuccess = true;
                                                               });
            }


            Monitor.Enter(_currentSendedWindow);

            if (_currentSendedWindow.GetByIndex(0).IsSuccess)
            {
                var sendedCount = _currentSendedWindow.Count;

                SendDataSegment[] tempSendList = new SendDataSegment[sendedCount];

                _currentSendedWindow.Values.CopyTo(tempSendList, 0);

                Monitor.Exit(_currentSendedWindow);

                for (int i = 0; i < sendedCount; i++)
                {
                    var item = tempSendList[i];

                    if (!item.IsSuccess)
                    {

                        break;
                    }

                    _currentSendedWindow.Remove(item.FragmentIndex);

                    if (item.IsLastFragment)
                    {
                        SendAsyncResult iar = null;

                        if (_cacheSendSyncResult.TryGetValue(item.BagID, out iar))
                        {
                            if (iar != null)
                            {
                                iar.Execute();
                                //_config.OnSendDataCompleted(iar);
                            }
                        }

                    }
                }


            }

            _bufferManager.ReturnBuffer(data);

            if (_isClosed && _sendQueue.Count == 0 && _currentSendedWindow.Count == 0)
            {
                OnSendClear();
            }
            else
            {
                FillAndSend();
            }



        }

        public void Stop()
        {
            _isClosed = true;

            lock (_sendQueue)
                lock (_currentSendedWindow)
                {
                    if (_sendQueue.Count == 0 && _currentSendedWindow.Count == 0)
                    {
                        OnSendClear();
                    }
                }
        }

        public void Close()
        {
            _nextSendIndex.Value = 0;

            Monitor.Enter(_sendQueue);

            _sendQueue.Clear();

            Monitor.Exit(_sendQueue);

            Monitor.Enter(_currentSendedWindow);

            _currentSendedWindow.Clear();

            Monitor.Exit(_currentSendedWindow);

            Monitor.Enter(_cacheSendSyncResult);

            var error = new RUDPRemoteNoResponseException();

            foreach (var asyncResult in _cacheSendSyncResult)
            {
                asyncResult.Value.Error = error;

                asyncResult.Value.Execute();
            }

            Monitor.Exit(_cacheSendSyncResult);
        }

        public int Count
        {
            get { return _sendQueue.Count + _currentSendedWindow.Count; }
        }

        public event EventHandler SendClear;

        //public event EventHandler

        //分解数据包为数据片,并放入发送队列
        private void EnqueueData(int bagID, byte[] data, int offset, int count)
        {
            if (data == null || !data.IsInEnableRange(offset, count))
            {
                throw new ArgumentOutOfRangeException("data");
            }

            //var _connectID = _config.ConnectID;
            var pageSize = _config.DataPageSize;

            Monitor.Enter(_sendQueue);

            if (count <= pageSize)
            {
                _sendQueue.Enqueue(new SendDataSegment(_connectID, bagID, _nextSendIndex.Value, data, offset, count, count) { IsLastFragment = true });

                _nextSendIndex.Increment();

            }
            else
            {
                var pageCount = (int)Math.Ceiling(((double)count / pageSize));

                for (int i = 0; i < pageCount - 1; i++)
                {
                    _sendQueue.Enqueue(new SendDataSegment(_connectID, bagID, _nextSendIndex.Value, data, offset, pageSize, count));

                    offset += pageSize;

                    _nextSendIndex.Increment();
                }

                offset = (pageCount - 1) * pageSize;

                _sendQueue.Enqueue(new SendDataSegment(_connectID, bagID, _nextSendIndex.Value, data, offset, count - offset, count) { IsLastFragment = true });

                _nextSendIndex.Increment();
            }

            Monitor.Exit(_sendQueue);
        }

        private int GetBagID()
        {
            return Interlocked.Increment(ref _bagID); ;
        }

        private int _lastSendBagID = -1;
        private void FillAndSend()
        {
            Monitor.Enter(_currentSendedWindow);

            var windowSize = _config.WindowSize;

            var inputCount = windowSize - _currentSendedWindow.Count;

            if (inputCount > 0 && _sendQueue.Count > 0)
            {
                Monitor.Enter(_sendQueue);

                for (int i = 0; i < inputCount; i++)
                {
                    SendDataSegment item;

                    if (_sendQueue.TryDequeue(out item))
                    {
                        _currentSendedWindow.Add(item.FragmentIndex, item);

                        if (item.BagID != _lastSendBagID)
                        {
                            OnBeforceSend(item);
                        }

                        _lastSendBagID = item.BagID;

                        SocketSend(item);
                    }
                    else
                    {
                        break;
                    }
                }

                Monitor.Exit(_sendQueue);
            }

            Monitor.Exit(_currentSendedWindow);
        }

        private void SocketSend(SendDataSegment item)
        {
            var tempData = item.BuildToBytes();//TODO:进行数据封包

            _config.SendData(tempData.Array, tempData.Offset, tempData.Count, (o) =>
            {
                //TODO:回收tempData.Array

                var t = (SendDataSegment)o;

                if (t != null)
                {
                    item.SendTime = DateTime.Now;
                }

                _bufferManager.ReturnBuffer(tempData.Array);

            }, item);

        }

        private void SendTimeOutChecker(object state)
        {
            //var item = (ConnectConfig)state;

            //if (state == null)
            //{
            //    return;
            //}

            //var sendWindow = item.SendQueue._currentSendedWindow;

            Monitor.Enter(_currentSendedWindow);

            if (_currentSendedWindow.Count > 0)
            {
                var timeOutTime = DateTime.Now.AddSeconds(-10);

                foreach (var segment in _currentSendedWindow)
                {
                    if (segment.Value.SendTime > timeOutTime)
                    {
                        if (segment.Value.SendedCount > 5)
                        {
                            //TODO:引发连接中断事件,并停止所有发送检测

                            if (_sendTimeoutCheckTimer != null)
                            {
                                _sendTimeoutCheckTimer.Stop();
                            }

                            OnDisconnected();

                        }
                        else
                        {
                            SocketSend(segment.Value);
                        }

                    }
                }
            }

            Monitor.Exit(_currentSendedWindow);
        }

        private void OnSendClear()
        {
            Events.EventHelper.Raise(SendClear, this);
        }

        private void OnDisconnected()
        {
            _config.Disconnection();

            //Events.EventHelper.Raise(Disconnected,this);
        }

        private void OnBeforceSend(SendDataSegment item)
        {

        }

        //internal bool EnqueueACK(short ackIndex)
        //{
        //    Monitor.Enter(_currentSendedWindow);

        //    bool IsNeedDefrag = false;

        //    if (_currentSendedWindow.ContainsKey(ackIndex))
        //    {
        //        var temp = _currentSendedWindow[ackIndex];

        //        temp.IsSuccess = true;

        //        IsNeedDefrag = temp == _currentSendedWindow.GetByIndex(0);
        //    }

        //    Monitor.Exit(_currentSendedWindow);

        //    return IsNeedDefrag;
        //}
    }

    internal class SlideWindowRevQueue
    {
        private LinkedListEx<RevItemSegment> _link = new LinkedListEx<RevItemSegment>();
        private short _startIndex;
        private readonly SortedList<short, RevItemSegment> _windowList = null;
        private short _windowSize;
        private AtomInt16 _lastEnqueueIndex = new AtomInt16(0);
        private readonly HashCircularQueue<short> _revedIndexCache = new HashCircularQueue<short>(20, null);
        private readonly object _lockerObj = new object();
        private bool isClosed = false;
        private BufferManager _bufferManager = null;
        private int _connectID;
        private ConnectConfig _config;
        private bool _isClosed = false;

        public SlideWindowRevQueue(ConnectConfig config, short startIndex, BufferManager bufferManager)
        {
            //if (windowSize <= 0)
            //{
            //    throw new ArgumentOutOfRangeException("windowSize");
            //}

            if (bufferManager == null)
            {
                throw new ArgumentNullException("bufferManager");
            }

            _startIndex = startIndex;
            _windowSize = config.WindowSize;
            _bufferManager = bufferManager;
            _connectID = config.ConnectID;
            _config = config;

            _windowList = new SortedList<short, RevItemSegment>(_windowSize);

            for (short i = _startIndex; i < _startIndex + _windowSize; i++)
            {
                _windowList.Add(i, null);
            }

        }

        public RevItemHandle EnQueue(RevItemSegment revItem)
        {
            if (_isClosed)
            {
                return RevItemHandle.None;
            }

            if (!_revedIndexCache.EnQueue(revItem.Index))
            {
                SendACK(revItem.Index);
                return RevItemHandle.Received;
            }

            Monitor.Enter(_lockerObj);

            if (_windowList.UpdateValue(revItem.Index, revItem))
            {
                LinkNodeEx<RevItemSegment> lastEndItemNode = null;

                if (revItem.Index == _lastEnqueueIndex.Value)
                {
                    short enqueueIndex = 0;// _link.Last.Value.Index.Increment();

                    if (_link.Count > 0)
                    {
                        enqueueIndex = _link.Last.Value.Index.Increment();
                    }

                    var currentCount = _windowList.Count;

                    for (int i = 0; i < currentCount; i++)
                    {
                        var tempItem = _windowList.GetByIndex(0);

                        if (tempItem != null && tempItem.Index == enqueueIndex)
                        {
                            var t = _link.AddLast(tempItem);

                            var newIndex = tempItem.Index.AddUnChecked(_windowSize);
                            enqueueIndex = enqueueIndex.Increment();
                            _windowList.RemoveAt(0);
                            _windowList.Add(newIndex, null);

                            if (tempItem.IsBagEnd) lastEndItemNode = t;

                        }
                        else
                        {
                            break;
                        }
                    }

                    _lastEnqueueIndex.Value = enqueueIndex;

                    SendACK(revItem.Index);

                    if (lastEndItemNode != null)
                    {

                        var lst = _link.CutTo(lastEndItemNode);

                        ThreadPool.QueueUserWorkItem(DefragBagList, lst);

                        //LinkNodeEx<RevItemSegment> node = _link.First;

                        //var cacheNode = new List<LinkedListNode<RevItemSegment>>();

                        //while (node != null)
                        //{
                        //    var buff = _bufferManager.TakeBuffer(node.Value.BagTotalLength);
                        //    var bs = new ByteStream(buff, 0, node.Value.BagTotalLength);

                        //    do
                        //    {
                        //        var current = node.Value;

                        //        bs.Write(current.Data.Array, current.Data.Offset, current.Data.Count);

                        //        cacheNode.Add(node);

                        //        if (current.IsBagEnd)
                        //        {
                        //            OnDataReceived(buff, 0, (int)bs.Position);
                        //            //TODO:引发接收函数
                        //            bs.Close();

                        //            bs.Dispose();

                        //            _bufferManager.ReturnBuffer(buff);

                        //            break;
                        //        }

                        //        node = node.Next;

                        //    } while (node != null);

                        //    if (node != lastEndItemNode && node != null)
                        //    {
                        //        node = node.Next;
                        //    }
                        //    else
                        //    {
                        //        for (int i = 0; i < cacheNode.Count; i++)
                        //        {
                        //            _link.Remove(cacheNode[i]);

                        //            _bufferManager.ReturnBuffer(cacheNode[i].Value.Data.Array);
                        //        }
                        //        break;
                        //    }

                        //}

                    }


                }

                Monitor.Exit(_lockerObj);

                return RevItemHandle.ACK;
            }
            else
            {
                Monitor.Exit(_lockerObj);
                return RevItemHandle.None;
            }

        }

        private void DefragBagList(object state)
        {
            var lst = (RevItemSegment[])state;

            if (lst.Length <= 0)
            {
                return;
            }

            byte[] buff = null;
            ByteStream bs = null;

            for (int i = 0; i < lst.Length; i++)
            {

                var current = lst[i];

                if (buff == null)
                {
                    buff = _bufferManager.TakeBuffer(current.BagTotalLength);
                    bs = new ByteStream(buff, 0, current.BagTotalLength);
                }

                bs.Write(current.Data.Array, current.Data.Offset, current.Data.Count);

                if (current.IsBagEnd)
                {
                    OnDataReceived(buff, 0, (int)bs.Position);


                    bs.Close();

                    bs.Dispose();

                    _bufferManager.ReturnBuffer(buff);
                    buff = null;

                    _bufferManager.ReturnBuffer(current.Data.Array);
                }
            }
        }

        public event EventHandler<RUDPDataReceivedEventArgs> DataReceived;

        public void Close()
        {
            lock (_lockerObj)
            {
                var linkList = _link.ToArray();

                _link.Clear();

                foreach (var revItemSegment in linkList)
                {
                    _bufferManager.ReturnBuffer(revItemSegment.Value.Data.Array);
                }

                foreach (var revItemSegment in _windowList)
                {
                    if (revItemSegment.Value != null)
                    {
                        _bufferManager.ReturnBuffer(revItemSegment.Value.Data.Array);
                    }

                }

                _windowList.Clear();

                _revedIndexCache.Clear();

                _bufferManager = null;

                isClosed = true;
            }
        }

        public void Stop()
        {
            _isClosed = true;
        }

        private void OnDataReceived(byte[] buffer, int offset, int count)
        {
            if (buffer != null)
            {
                for (int i = 0; i < count; i++)
                {
                    if (buffer[i] != (byte)i)
                    {

                    }
                }
            }

            Events.EventHelper.Raise(DataReceived, this, new RUDPDataReceivedEventArgs(buffer, offset, count) { ConnectID = _connectID });
        }

        private void SendACK(short index)
        {
            var tempData = ACKData.Create(_connectID, new[] { index });//TODO:进行数据封包

            _config.SendData(tempData.Array, tempData.Offset, tempData.Count, (o) => _bufferManager.ReturnBuffer(tempData.Array), null);
        }

        //private void BuildDataBag(object state)
        //{
        //    Monitor.Enter(_lockerObj);

        //    do
        //    {
        //        var currentIndex = _windowList.Count;
        //        bool needBuild = false;

        //        if (currentIndex > 0)
        //        {
        //            short enqueueIndex = _link.Last.Value.Index;

        //            do
        //            {
        //                unchecked
        //                {
        //                    enqueueIndex++;
        //                }

        //                var item = (RUDP.RevItemSegment)_windowList.GetByIndex(0);

        //                if (enqueueIndex == item.Index)
        //                {
        //                    _windowList.Remove(item.Index);

        //                    _link.AddLast(item);
        //                    if (item.IsEnd)
        //                    {
        //                        needBuild = true;
        //                    }
        //                }
        //                else
        //                {
        //                    break;
        //                }

        //                currentIndex--;

        //            } while (currentIndex < 0);
        //        }

        //        if (needBuild)
        //        {
        //            LinkedListNode<RUDP.RevItemSegment> currentNode = _link.First;

        //            do
        //            {
        //                if (currentNode.Value.IsEnd)
        //                {
        //                    var tempItem = _link.First;
        //                    var buffer = _bufferManager.TakeBuffer(8192);
        //                    var bs = new ByteStream(buffer, 0);

        //                    do
        //                    {

        //                        _link.RemoveFirst();
        //                        tempItem.Value = null;

        //                        bs.Write(tempItem.Value.Data.Array, tempItem.Value.Data.Offset + 9, tempItem.Value.Data.Count - 9);

        //                    } while (tempItem != currentNode);

        //                    //TODO:复制List中的数据区，并拼凑成一个数组引发收到数据的事件
        //                    bs.Dispose();

        //                    OnDataBuildSuccess(new ArraySegment<byte>(buffer, 0, (int)bs.Position));

        //                }

        //                currentNode = currentNode.Next;



        //            } while (currentNode != null);
        //        }


        //        if (isClosed)
        //        {
        //            break;
        //        }

        //        Monitor.Wait(_lockerBuilderObj, 2000);
        //    } while (!isClosed);


        //    Monitor.Exit(_lockerObj);
        //}
    }

    internal class RevItemSegment : IComparer
    {
        public short Index;
        public ArraySegment<byte> Data;
        public bool IsBagEnd;
        //public int ConnectID;
        public short BagTotalLength;

        public static RevItemSegment Load(byte[] data, int offset, int count)
        {
            var temp = new RevItemSegment();

            //temp.ConnectID = BitConverter.ToInt32(data, offset + 2);
            temp.Index = BitConverter.ToInt16(data, offset + 6);
            temp.BagTotalLength = BitConverter.ToInt16(data, offset + 8);
            temp.IsBagEnd = data[offset + 10] == 1;
            temp.Data = new ArraySegment<byte>(data, offset + 11, count - 13);

            return temp;
        }

        #region Implementation of IComparer

        public int Compare(object x, object y)
        {
            return ((RevItemSegment)x).Index - ((RevItemSegment)y).Index;
        }

        #endregion
    }

    internal class ACKData
    {
        private int _connectID = 0;
        private short[] _ackList = null;

        public ACKData(int connectId, short[] ackList)
        {
            _connectID = connectId;
            _ackList = ackList;
        }


        public int ConnectID { get { return _connectID; } }
        public short[] ACKList { get { return _ackList; } }

        public static ACKData Load(ArraySegment<byte> data)
        {
            var connectID = BitConverter.ToInt32(data.Array, data.Offset + 2);

            var count = data.Array[data.Offset + 6];

            if (count <= 0)
            {
                return null;
            }

            var ackList = new short[count];

            for (int i = 0; i < count; i++)
            {
                ackList[i] = BitConverter.ToInt16(data.Array, data.Offset + 7 + i * 2);
            }

            var t = new ACKData(connectID, ackList);

            return t;
        }

        public static ArraySegment<byte> Create(int connectID, short[] ackList)
        {
            var buff = new byte[ackList.Length * 2 + 9];
            var bs = new ByteStream(buff);

            bs.WriteByte(0x01);
            bs.WriteByte((byte)RUDPCmd.DataACK);
            bs.Write(BitConverter.GetBytes(connectID));
            bs.WriteByte((byte)ackList.Length);

            foreach (var ackIndex in ackList)
            {
                bs.Write(BitConverter.GetBytes(ackIndex));
            }

            bs.Write(buff.GetCRCCodeBytes(0, ackList.Length * 2 + 7));

            return new ArraySegment<byte>(buff, 0, ackList.Length * 2 + 9);
        }
    }

    internal class SendDataSegment : IEquatable<SendDataSegment>
    {
        public int BagID;
        public short FragmentIndex;
        public byte[] Data;
        public int Offset;
        public int Count;
        public bool IsSuccess;
        public DateTime? SendTime;
        public bool IsLastFragment;
        public byte SendedCount;
        public int ConnectID;
        public short TotalLength;

        public SendDataSegment(int connectID, int bagId, short fragmentIndex, byte[] data, int offset, int segmentCount, int bagTotalLength)
        {
            BagID = bagId;
            FragmentIndex = fragmentIndex;
            Data = data;
            Offset = offset;
            Count = segmentCount;
            IsLastFragment = false;
            ConnectID = connectID;
            TotalLength = (short)bagTotalLength;
        }

        public ArraySegment<byte> BuildToBytes()
        {
            var buff = new byte[13 + Count];
            var bs = new ByteStream(buff);

            bs.WriteByte(0x01);

            bs.WriteByte((byte)RUDPCmd.Data);

            bs.Write(ConnectID);
            bs.Write(BitConverter.GetBytes(FragmentIndex));
            bs.Write(BitConverter.GetBytes(TotalLength));

            bs.WriteByte(IsLastFragment ? (byte)1 : (byte)0);

            bs.Write(Data, Offset, Count);

            bs.Write(buff.GetCRCCode(0, 11 + Count));

            bs.Dispose();

            return new ArraySegment<byte>(buff, 0, 13 + Count);
        }

        public bool Equals(SendDataSegment other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return other.BagID == BagID && other.FragmentIndex == FragmentIndex && other.ConnectID == ConnectID;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof(SendDataSegment)) return false;
            return Equals((SendDataSegment)obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                int result = BagID;
                result = (result * 397) ^ FragmentIndex;
                result = (result * 397) ^ ConnectID;
                return result;
            }
        }

        public static bool operator ==(SendDataSegment left, SendDataSegment right)
        {
            return Equals(left, right);
        }

        public static bool operator !=(SendDataSegment left, SendDataSegment right)
        {
            return !Equals(left, right);
        }
    }

    public class RUDPConnection
    {
        private int _connectID;
        private ConnectConfig _rUDPLink;

        internal RUDPConnection(int connectId, ConnectConfig rUdpLink)
        {
            _connectID = connectId;
            _rUDPLink = rUdpLink;
        }

        public IAsyncResult BeginSend(byte[] data, int offset, int count, AsyncCallback callback, object state)
        {
            return _rUDPLink.BeginSend(data, offset, count, callback, state);
        }

        public int EndSend(IAsyncResult iar)
        {
            return _rUDPLink.EndSend(iar);
        }

        public int ConnectID
        {
            get { return _connectID; }
        }

        public void Close()
        {
            _rUDPLink.StartClose();
        }



        public event EventHandler<RUDPDataReceivedEventArgs> DataReceive;

        public event EventHandler<RUDPDisconnectedEventArgs> Disconnected;

        //public event EventHandler<RUDPDisconnectedEventArgs> Disconnected;

        internal void OnReceiveData(RUDPDataReceivedEventArgs e)
        {
            Events.EventHelper.RaiseAsync(DataReceive, this, e);
        }

        internal void OnDisconnected(RUDPDisconnectedEventArgs e)
        {
            Events.EventHelper.Raise(Disconnected, this, e);
        }
    }

    internal class SendAsyncResult : IAsyncResult
    {
        private Lazy<AutoResetEvent> _lazyValue;
        private bool _isCompleted;
        private int _dataLength;
        private AsyncCallback _callback;
        private object _state;
        private int _bagID;
        private int _connectID;
        private Exception _error;


        public SendAsyncResult(int bagId, int dataLength, AsyncCallback callback, object state, Exception error = null)
        {
            _lazyValue = new Lazy<AutoResetEvent>(BuildWaitHandle);
            _dataLength = dataLength;
            _callback = callback;
            _bagID = bagId;
            _state = state;
            _isCompleted = false;
            _error = error;
        }

        public int DataLength { get { return _dataLength; } }
        public AsyncCallback Callback { get { return _callback; } }
        public int BagID { get { return _bagID; } }
        public int ConnectID { get { return _connectID; } }


        public Exception Error
        {
            get { return _error; }
            internal set { _error = value; }
        }

        public bool HasError
        {
            get { return Error != null; }
        }

        internal void Execute()
        {
            if (_callback != null)
            {
                ThreadPool.QueueUserWorkItem((s) => _callback(this));
            }

        }

        #region Implementation of IAsyncResult

        public bool IsCompleted
        {
            get { return _isCompleted; }
            set
            {
                _isCompleted = value;

                if (value)
                {
                    if (_lazyValue.IsValueCreated)
                    {
                        _lazyValue.Value.Set();
                    }
                }
            }
        }

        public WaitHandle AsyncWaitHandle
        {
            get { return _lazyValue.Value; }
        }

        public object AsyncState
        {
            get { return _state; }
        }

        public bool CompletedSynchronously
        {
            get { return false; }
        }

        #endregion

        private AutoResetEvent BuildWaitHandle()
        {
            return new AutoResetEvent(false);
        }
    }

    public class RUDPDataReceivedEventArgs : EventArgs
    {
        public RUDPDataReceivedEventArgs(byte[] data, int offset, int count)
        {
            Data = data;
            Offset = offset;
            Count = count;
        }

        public int ConnectID;
        public byte[] Data;
        public int Offset;
        public int Count;
    }

    public class RUDPConnectRequestEventArgs : EventArgs
    {
        public RUDPConnectRequestEventArgs(IPEndPoint remotePoint)
        {
            RemotePoint = remotePoint;
            Cancel = false;
        }

        public IPEndPoint RemotePoint { private set; get; }

        public bool Cancel { set; get; }
    }

    public class RUDPConnectSuccessEventArgs : EventArgs
    {
        public RUDPConnectSuccessEventArgs(RUDPConnection connection)
        {
            Connection = connection;
        }

        public RUDPConnection Connection { private set; get; }
    }

    public class RUDPDisconnectedEventArgs : EventArgs
    {
        private Exception _error;
        private RUDPConnection _connection;

        internal RUDPDisconnectedEventArgs(RUDPConnection connection, Exception error = null)
        {
            _connection = connection;
            _error = error;
        }

        public RUDPConnection Connection { get { return _connection; } }

        public Exception Error { get { return _error; } }

        public bool HasError { get { return _error != null; } }
    }

    public class RUDPRemoteNoResponseException : Exception
    {
        public RUDPRemoteNoResponseException() : base("远程计算机无响应") { }
    }

    internal enum RevItemHandle
    {
        None,
        Received,
        ACK
    }

    internal enum RUDPCmd : byte
    {
        Data = 0x01,

        DataACK = 0x02,

        HandShake_ConnectRequest = 0xF0,
        HandShake_ConnectResponse = 0xF1,
        HandShake_ConnectSuccess = 0xF2,

        HandShake_Fin = 0xF3,
        HandShake_Fin_ACK = 0xF4,
        HandShake_FinSendClear = 0xF5,
        HandShake_FinSendClear_ACK = 0xF6,


        //HandShake_ConnectSuccessACK = 0xF3,
        KeepActive = 0xE0,
        KeepActive_ACK = 0xE1,



    }

    internal class RevSlideWindow<T> where T : class,ISegmentBase
    {
        private short _windowSize = 5;
        private LinkedListEx<T> _link = new LinkedListEx<T>();

        private LinkNodeEx<T> _nodeFront = null;
        private short _linkIndexFront = 0;
        private short _linkIndexRear = 0;
        private int _windowCurrentIndex = 0;
        private int _windowMaxIndex = 5;

        private short _enqueueIndex = 0;

        private short _startIndex = 0;

        private LinkNodeEx<T>[] _window = null;

        private ReaderWriterLockSlim lockSlim = new ReaderWriterLockSlim();

        public RevSlideWindow(int windowSize, short startIndex)
        {
            _linkIndexFront = startIndex;

            _window = new LinkNodeEx<T>[windowSize];

            _windowCurrentIndex = -1;
            _windowMaxIndex = windowSize - 1;
            _enqueueIndex = startIndex;

            unchecked
            {
                _linkIndexRear = (short)(startIndex + windowSize);
            }

            for (int i = 0; i < windowSize; i++)
            {
                _link.AddLast(new LinkNodeEx<T>(null));
            }
        }

        public bool AddOrUpdate(T value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            var isSuccess = true;
            lockSlim.EnterWriteLock();

            //LinkNodeEx<T> retItem = null;

            LinkNodeEx<T> item = null;

            for (int i = 0; i < _windowCurrentIndex; i++)
            {
                var n = _window[i];

                if ((n.Value != null && n.Value.Index == value.Index))// || (n.Value == null && _linkIndexFront + i == value.Index))
                {
                    item = n;
                    break;
                }
            }

            if (item != null)
            {
                item.Value = value;

            }
            else
            {
                //if (_link.Last!=null && )
                //{
                //    if (_link.Last.Value.Index+1==value.Index)
                //    {
                //        _link.AddLast(value);
                //    }         
                //}
                //else
                //{
                if (value.Index == _enqueueIndex)
                {
                    _link.AddLast(value);
                    unchecked
                    {
                        _enqueueIndex += 1;
                    }
                    //}
                }

                if (_windowCurrentIndex < _windowMaxIndex)
                {
                    if (_windowCurrentIndex >= 0)
                    {
                        if (_window[_windowCurrentIndex].Next != null)
                        {
                            _window[_windowCurrentIndex + 1] = _window[_windowCurrentIndex].Next;
                            Interlocked.Increment(ref _windowCurrentIndex);
                        }
                    }
                    else
                    {
                    }
                }
            }








            //var check = CheckIndexRang(value.Index);

            //if (check == 0)
            //{
            //    if (value.Index == _linkIndexFront)
            //    {
            //        _nodeFront.Value = value;
            //    }
            //    else
            //    {
            //        LinkNodeEx<T> item = null;

            //        for (int i = 0; i < _window.Length; i++)
            //        {
            //            var n = _window[i];

            //            if ((n.Value != null && n.Value.Index == value.Index) || (n.Value == null && _linkIndexFront+i == value.Index))
            //            {
            //                item = n;
            //                break;
            //            }
            //        }

            //        if (item != null)
            //        {
            //            item.Value = value;
            //        }
            //    }
            //}
            //else if(check>0)
            //{
            //    var node=_link.AddLast(value);

            //    if (_windowCurrentIndex < _windowMaxIndex)
            //    {
            //        _window[_windowCurrentIndex] = node;
            //        Interlocked.Increment(ref _windowCurrentIndex);
            //    }
            //}
            //else
            //{
            //    isSuccess = false;
            //}

            lockSlim.ExitWriteLock();

            return isSuccess;
        }

        public void Move()
        {
            if (_windowCurrentIndex < 0)
            {
                return;
            }






            if (_nodeFront.Value != null)
            {
                var tempNode = _nodeFront;

                short c = 0;

                while (tempNode.Value != null)
                {
                    c += 1;
                    _link.AddLast(new LinkNodeEx<T>(null));
                }

                _nodeFront = tempNode;
                _linkIndexFront.AddUnChecked(c);

            }

            unchecked
            {
                _linkIndexRear = (short)(_linkIndexFront + _windowSize);
            }
        }

        public int CheckIndexRang(short index)
        {
            var tempStartIndex = _linkIndexFront;
            var tempEndIndex = _linkIndexRear;

            if (index == tempStartIndex || tempEndIndex == index)
            {
                return 0;
            }

            unchecked
            {
                tempEndIndex = (short)(tempStartIndex + _windowSize);
            }

            if (tempStartIndex > tempEndIndex)
            {
                if (index <= tempEndIndex || index >= tempStartIndex)
                {
                    return 0;
                }
            }
            else
            {
                if (index >= tempStartIndex && index <= tempEndIndex)
                {
                    return 0;
                }
            }

            return -1;
        }

        //public bool MoveNext()
        //{
        //    lockSlim.EnterWriteLock();




        //    lockSlim.ExitWriteLock();
        //}


        private class SildeWindowNode
        {
            public ISegmentBase Value;
            public short Index;
        }

        //public RevItemSegment[] MoveNext()
        //{

        //}
    }

    internal interface ISegmentBase
    {
        short Index { get; }
    }

    public enum ConnectStatus
    {
        None = 0,
        Syn_Send,
        Syn_Rev,
        ESTABLISHED,
        Stop,


        Fin_Wait1,
        Fin_Wait2,
        Time_Wait,

        Close_Wait,
        Last_ACK,

        Closed
    }



    //internal class RUDPLink
    //{
    //    private Dictionary<int, ConnectConfig> _cacheConnectConfig = new Dictionary<int, ConnectConfig>(10);

    //    private NewRUDP _udpServer;
    //    private TimerPool _timerPool = null;
    //    private object _lockObj = new object();
    //    private BufferManager _bufferManager = null;

    //    internal RUDPLink(NewRUDP udpServer, BufferManager bufferManager)
    //    {
    //        _udpServer = udpServer;
    //        _timerPool = new TimerPool(2);
    //        _bufferManager = bufferManager;

    //    }

    //    internal RUDPConnection AddConnection(int connectID, int dataPageSize, short windowSize, IPEndPoint remotePoint)
    //    {
    //        try
    //        {
    //            lock (_lockObj)
    //            {
    //                _cacheConnectConfig.Add(connectID, null);

    //                var connectionConfig = new ConnectConfig(this, connectID, windowSize, dataPageSize, remotePoint, _bufferManager);

    //                _cacheConnectConfig[connectID] = connectionConfig;

    //                //_timerPool.Add(2000, SendTimeOutChecker, connectionConfig, true);

    //                return connectionConfig.Item;

    //            }

    //        }
    //        catch (Exception)
    //        {
    //            return null;
    //        }

    //    }

    //    internal void DataReceive(int connectID, byte[] data, int offset, int count)
    //    {
    //        //var connectID = BitConverter.ToInt32(data,offset + 2);

    //        switch (data[offset + 1])
    //        {
    //            case 0x01:
    //            case 0x03:
    //                EnQueueDataItem(connectID, data, offset, count);
    //                break;
    //            case 0x02:
    //                EnQueueACK(connectID, data, offset, count);
    //                break;
    //        }
    //    }

    //    internal bool ContansConnection(int connectID)
    //    {
    //        return _cacheConnectConfig.ContainsKey(connectID);
    //    }

    //    internal int Count
    //    {
    //        get { return _cacheConnectConfig.Count; }
    //    }

    //    internal int[] GetConnectIDList()
    //    {
    //        var idList = _cacheConnectConfig.Keys;

    //        return idList.ToArray();
    //    }

    //    internal RUDPConnection this[int connectID]
    //    {
    //        get
    //        {
    //            var t = _cacheConnectConfig.TryGetValue(connectID);

    //            if (t != null)
    //            {
    //                return t.Item;
    //            }
    //            else
    //            {
    //                return null;
    //            }

    //        }
    //    }


    //    #region "数据接收"

    //    internal void EnQueueDataItem(int connectID, byte[] data, int offset, int count)
    //    {
    //        ConnectConfig connectConfig = null;

    //        if (_cacheConnectConfig.TryGetValue(connectID, out connectConfig))
    //        {
    //            var revItem = RevItemSegment.Load(new ArraySegment<byte>(data, offset, count));

    //            if (revItem == null)
    //            {
    //                return;
    //            }
    //            var handle = connectConfig.RevQueue.EnQueue(revItem);

    //            if (handle == RevItemHandle.None)
    //            {
    //                return;
    //            }

    //            SocketACK(connectConfig.ConnectID, new[] { revItem.Index }, connectConfig.RemotePoint);
    //        }
    //        else
    //        {
    //            return;
    //        }
    //    }


    //    private void SocketACK(int connectID, short[] ackList, IPEndPoint remotePoint)
    //    {
    //        var tempData = ACKData.Create(connectID, ackList);//TODO:进行数据封包

    //        _udpServer.SendData(tempData.Array, tempData.Offset, tempData.Count, remotePoint, (o) =>
    //        {
    //            //TODO:回收tempData.Array
    //        }, null);

    //        //_udpServer._socket.BeginSendTo(tempData.Array, tempData.Offset, tempData.Count, SocketFlags.None,
    //        //                                remotePoint, SocketACKCallback, null);

    //    }

    //    #endregion

    //    #region "数据发送"

    //    internal IAsyncResult BeginSend(int connectID, byte[] data, int offset, int count, AsyncCallback callback, object state)
    //    {
    //        ConnectConfig config = null;

    //        if (_cacheConnectConfig.TryGetValue(connectID, out config))
    //        {
    //            //int tempBagID = Interlocked.Increment(ref _bagID); ;

    //            int tempBagID = config.GetBagID();

    //            config.SendQueue.Enqueue(connectID, tempBagID, data, offset, count);

    //            FillAndSend(config);

    //            var iar = new SendAsyncResult(tempBagID, count, callback, state);

    //            config.AddAsyncResult(tempBagID, iar);

    //            return iar;

    //        }
    //        else
    //        {
    //            throw new Exception("连接不存在");
    //        }

    //    }

    //    internal int EndSend(IAsyncResult iar)
    //    {
    //        var item = (SendAsyncResult)iar;

    //        //if (item.Callback == null)
    //        //{
    //        //    throw new Exception();
    //        //}

    //        ConnectConfig config = null;

    //        if (_cacheConnectConfig.TryGetValue(item.ConnectID, out config))
    //        {
    //            config.RemoveAsyncResult(item.BagID);
    //        }

    //        //Monitor.Enter(_cacheSendSyncResult);

    //        //_cacheSendSyncResult.Remove(item.BagID);

    //        //Monitor.Exit(_cacheSendSyncResult);

    //        return item.DataLength;
    //    }

    //    internal void EnQueueACK(int connectID, byte[] data, int offset, int count)
    //    {
    //        ConnectConfig config = null;

    //        if (_cacheConnectConfig.TryGetValue(connectID, out config))
    //        {
    //            var sendWindow = config.SendQueue._currentSendedWindow;

    //            var ackCount = data[offset + 6];

    //            if (ackCount <= 0 || ackCount * 2 + 9 > count)
    //            {
    //                _bufferManager.ReturnBuffer(data);
    //                return;
    //            }

    //            for (int i = 0; i < ackCount; i += 2)
    //            {
    //                var ackIndex = BitConverter.ToInt16(data, offset + 7 + i);

    //                sendWindow.UpdateValue(ackIndex, (s) =>
    //                {
    //                    s.IsSuccess = true;
    //                });
    //            }


    //            Monitor.Enter(sendWindow);

    //            if (sendWindow.GetByIndex(0).IsSuccess)
    //            {
    //                var sendedCount = sendWindow.Count;

    //                SendDataSegment[] tempSendList = new SendDataSegment[sendedCount];

    //                sendWindow.Values.CopyTo(tempSendList, 0);

    //                Monitor.Exit(sendWindow);

    //                for (int i = 0; i < sendedCount; i++)
    //                {
    //                    var item = tempSendList[i];

    //                    if (!item.IsSuccess)
    //                    {

    //                        break;
    //                    }

    //                    sendWindow.Remove(item.FragmentIndex);

    //                    if (item.IsLastFragment)
    //                    {
    //                        SendAsyncResult iar = config.GetAsyncResult(item.BagID);

    //                        if (iar != null)
    //                        {
    //                            config.Item.OnSendDataCompleted(iar);
    //                        }

    //                    }
    //                }

    //                FillAndSend(config);
    //            }
    //            else
    //            {
    //                Monitor.Exit(sendWindow);
    //            }


    //        }

    //        _bufferManager.ReturnBuffer(data);


    //    }

    //    internal void Close(int connectID)
    //    {

    //    }

    //    private void FillAndSend(ConnectConfig config)
    //    {
    //        var sendWindow = config.SendQueue._currentSendedWindow;

    //        Monitor.Enter(sendWindow);

    //        var sendQueue = config.SendQueue._sendQueue;

    //        var inputCount = config.WindowSize - sendWindow.Count;

    //        if (inputCount > 0 && sendQueue.Count > 0)
    //        {
    //            Monitor.Enter(sendQueue);

    //            for (int i = 0; i < inputCount; i++)
    //            {
    //                SendDataSegment item;

    //                if (sendQueue.TryDequeue(out item))
    //                {
    //                    sendWindow.Add(item.FragmentIndex, item);
    //                    SocketSend(item, config.RemotePoint);
    //                }
    //                else
    //                {
    //                    break;
    //                }
    //            }

    //            Monitor.Exit(sendQueue);
    //        }

    //        Monitor.Exit(sendWindow);
    //    }

    //    private void SocketSend(SendDataSegment item, IPEndPoint remotePoint)
    //    {
    //        var tempData = item.BuildToBytes();//TODO:进行数据封包

    //        _udpServer.SendData(tempData.Array, tempData.Offset, tempData.Count, remotePoint, (o) =>
    //        {
    //            //TODO:回收tempData.Array

    //            var t = (SendDataSegment)o;

    //            if (t != null)
    //            {
    //                item.SendTime = DateTime.Now;
    //            }

    //            _bufferManager.ReturnBuffer(tempData.Array);

    //        }, item);

    //        //_udpServer._socket.BeginSendTo(tempData.Array, tempData.Offset, tempData.Count, SocketFlags.None,
    //        //                                remotePoint, SocketSendCallback, item);

    //        //TODO:回收tempData.Array
    //    }

    //    private void SendTimeOutChecker(object state)
    //    {
    //        var item = (ConnectConfig)state;

    //        if (state == null)
    //        {
    //            return;
    //        }

    //        var sendWindow = item.SendQueue._currentSendedWindow;

    //        Monitor.Enter(sendWindow);

    //        if (sendWindow.Count > 0)
    //        {
    //            var timeOutTime = DateTime.Now.AddSeconds(-10);

    //            foreach (var segment in sendWindow)
    //            {
    //                if (segment.Value.SendTime > timeOutTime)
    //                {
    //                    if (segment.Value.SendedCount > 5)
    //                    {
    //                        //TODO:引发连接中断事件,并停止所有发送检测
    //                    }
    //                    else
    //                    {
    //                        SocketSend(segment.Value, item.RemotePoint);
    //                    }

    //                }
    //            }
    //        }

    //        Monitor.Exit(sendWindow);
    //    }

    //    #endregion
    //}

    //internal enum CmdID : byte
    //{
    //    Unknow = 0x00,
    //    SendCmd = 0x01,
    //    RevACK = 0x02,


    //    HandShake_SYN_ConnectRequest = 0xF0,
    //    HandShake_SYN_ConnectAccept = 0xF1,
    //    HandShake_SYN_ConnectAcceptACK = 0xF2,

    //    KeepActive = 0xE0,
    //    KeepActiveACK = 0xE1


    //}
}
